package com.spark.modules.system.utils;

import com.spark.modules.system.entity.SysPermission;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 * 构建菜单树
 *
 * @author LYCHEE
 * @date 2025/2/18 15:01
 */
public class MenuBuilder {

    /**
     * 构建菜单树
     *
     * @param sysPermissions 菜单权限列表
     * @return 构建后的菜单树
     */
    public static List<Map<String, Object>> buildMenuTree(List<SysPermission> sysPermissions) {
        Map<String, Map<String, Object>> menuMap = new HashMap<>();
        List<Map<String, Object>> rootMenus = new ArrayList<>();
        // 初始化所有节点
        for (SysPermission permission : sysPermissions) {
            boolean flag = "0".equals(permission.getPid()) && 1 == permission.getType();
            Map<String, Object> node = createMenuNode(permission,flag);
            menuMap.put(permission.getId(), node);
            if ("0".equals(permission.getPid())) {
                rootMenus.add(node);
            } else {
                // 初始化 children 列表，即使该节点还没有子节点
                ((Map<String, Object>) node).put("children", new ArrayList<>());
            }
        }

        // 构建子节点
        for (SysPermission permission : sysPermissions) {
            String parentId = permission.getPid();
            if (!"0".equals(parentId)) {
                Map<String, Object> parent = menuMap.get(parentId);
                if (parent != null) {
                    @SuppressWarnings("unchecked")
                    List<Map<String, Object>> children = (List<Map<String, Object>>) parent.computeIfAbsent("children", k -> new ArrayList<>());
                    Map<String, Object> stringObjectMap = menuMap.get(permission.getId());
                    //Map<String, Object> parentMap = menuMap.get(permission.getPid());
                    //if (!CollectionUtils.isEmpty(parentMap)){
                    //    String parentPath = (String) parentMap.get("path");
                    //    stringObjectMap.put("path", parentPath.concat((String) stringObjectMap.get("path")));
                    //}
                    children.add(stringObjectMap);
                }
            }else if (1 == permission.getType()){
                // 当一级是菜单时：只显示本级，如果添加下级菜单,则不处理
                Map<String, Object> parent = menuMap.get(permission.getId());
                if (parent != null) {
                    @SuppressWarnings("unchecked")
                    List<Map<String, Object>> children = (List<Map<String, Object>>) parent.computeIfAbsent("children", k -> new ArrayList<>());
                    // 为一级菜单创建子菜单
                    Map<String, Object> node = createMenuNode(permission,false);
                    //node.put("path", (String) parent.get("path") + node.get("path"));
                    @SuppressWarnings("unchecked")
                    Map<String,Object> meta = (Map<String,Object>)node.get("meta");
                    meta.put("order",-1);
                    children.add(node);
                }
            }
        }

        // 对整棵树进行排序
        sortMenuTree(rootMenus);

        return rootMenus;
    }

    /**
     * 处理数据
     *
     * @param permission 菜单
     * @param isMenu 第一级是否是菜单 true
     * @return MenuNode
     */
    private static Map<String, Object> createMenuNode(SysPermission permission, boolean isMenu) {
        Map<String, Object> node = new HashMap<String, Object>();
        node.put("name",dealName(permission.getRoutePath()));
        node.put("path",permission.getRoutePath());
        // 多级路由的父级路由无需设置 component 属性，只需设置 children 属性即可。除非你真的需要在父级路由嵌套下显示内容。
        // 是顶级节点设置 component 属性
        if ("0".equals(permission.getPid())){
            node.put("component",permission.getComponentPath());
        }else if (!(Boolean) permission.getIsLeaf()){
            // 是叶子节点，设置 component 属性
            node.put("component",permission.getComponentPath());
        }
        // 设置属性Map
        Map<String,Object> meta = new HashMap<>();
        meta.put("title", permission.getName());
        meta.put("icon", permission.getIcon());
        meta.put("order",permission.getSortRank() == null ? 0 : permission.getSortRank());
        if (!isMenu){
            if(permission.getIsKeepAlive() == 0){
                meta.put("keepAlive", true);
            }
            if(permission.getIsHideInMenu() == 0){
                meta.put("hideInMenu", true);
            }
            if(permission.getIsHideInTab() == 0){
                meta.put("hideInTab", true);
            }
            if(permission.getIsHideInBreadcrumb() == 0){
                meta.put("hideInBreadcrumb", true);
            }
            if(permission.getIsHideChildrenInMenu() == 0){
                meta.put("hideChildrenInMenu", true);
            }
            // 菜单权限
            if (StringUtils.isNotEmpty(permission.getAuthorityStr())){
                String[] split = permission.getAuthorityStr().split(",");
                meta.put("authority", split);
            }
            // 徽标
            if (permission.getIsBadge() == 0) {
                meta.put("badgeType",permission.getBadgeType());
                // 类型 红点 | 文本
                if ("dot".equals(permission.getBadgeType())){
                    meta.put("badgeVariants",permission.getBadgeVariants());
                }else {
                    meta.put("badge",permission.getBadgeValue());
                    meta.put("badgeVariants",permission.getBadgeVariants());
                }
            }
            // 是否固定标签页 && 标签页没有隐藏
            if (permission.getIsAffixTab() == 0 && permission.getIsHideInTab() == 1){
                meta.put("affixTab",true);
                meta.put("affixTabOrder",null == permission.getAffixTabOrder() ? 0 :permission.getAffixTabOrder());
            }
            // 是否外链
            if (permission.getIsLink() == 0 && StringUtils.isNotEmpty(permission.getLink())){
                if (0 == permission.getLinkOpenWay()){
                    meta.put("link",permission.getLink());
                }else {
                    meta.put("iframeSrc",permission.getLink());
                }
            }
            // 用于配置页面在菜单可以看到，但是访问会被重定向到403。
            if(permission.getIsMenuVisibleWithForbidden() == 0){
                meta.put("menuVisibleWithForbidden", true);
            }
            // 设置为 true 时，会在新窗口打开页面。
            if(permission.getOpenInNewWindow() == 0){
                meta.put("openInNewWindow", true);
            }
            if (StringUtils.isNotEmpty(permission.getQuery())){
                meta.put("query",permission.getQuery());
            }
        } else {
            // 如果是一级菜单,需要设置一下
            node.put("name",dealName(permission.getRoutePath()).concat("Hide"));
            node.put("component","BasicLayout");
            node.put("path",permission.getRoutePath().concat("/").concat("hide"));
            // 设置子菜单隐藏
            meta.put("hideChildrenInMenu", true);
            // 隐藏菜单
            if(permission.getIsHideInMenu() == 0){
                meta.put("hideInMenu", true);
            }
            // 徽标
            if (permission.getIsBadge() == 0) {
                meta.put("badgeType",permission.getBadgeType());
                // 类型 红点 | 文本
                if ("dot".equals(permission.getBadgeType())){
                    meta.put("badgeVariants",permission.getBadgeVariants());
                }else {
                    meta.put("badge",permission.getBadgeValue());
                    meta.put("badgeVariants",permission.getBadgeVariants());
                }
            }
        }
        node.put("meta", meta);
        return node;
    }

    /**
     * 对树进行排序
     * @param nodes 树节点列表
     */
    public static void sortMenuTree(List<Map<String, Object>> nodes) {
        if (nodes == null || nodes.isEmpty()) {
            return;
        }
        // 使用 lambda 表达式简化排序逻辑
        nodes.sort(Comparator.comparingDouble(o -> getMetaOrderOrDefault(o, Integer.MAX_VALUE)));
        // 递归地对每个节点的子节点排序
        nodes.forEach(node -> {
            List<Map<String, Object>> children = (List<Map<String, Object>>)node.get("children");
            if (children != null && !children.isEmpty()) {
                sortMenuTree(children);
            }
        });
    }

    /**
     * 获取 meta 中的 order 值，如果不存在则返回默认值
     * @param node 菜单节点
     * @param defaultValue 默认值
     * @return meta 中的 order 值或默认值
     */
    private static double getMetaOrderOrDefault(Map<String, Object> node, double defaultValue) {
        Map<String, Object> meta = (Map<String, Object>)node.get("meta");
        if (meta != null && meta.containsKey("order") && meta.get("order") instanceof Number) {
            return ((Number) meta.get("order")).doubleValue();
        }
        return defaultValue;
    }

    /**
     * 处理Name
     * @param name name
     * @return name
     */
    private static String dealName(String name) {
        if (name == null || name.isEmpty()) {
            return name;
        }
        // 如果第一个字符是斜杠，则去掉
        if (name.charAt(0) == '/' && name.length() != 1) {
            name = name.substring(1);
        }
        // 将第一个字符转换为大写
        char firstChar = Character.toUpperCase(name.charAt(0));
        // 将第一个字符替换为大写后的字符
        String firstCharStr = firstChar + name.substring(1);
        // 正则表达式匹配以 "/:" 开头的任意字符序列作为后缀， 配置参数为：/:变量
        return firstCharStr.replaceAll("/:[^/]+$", "");
    }

}
